/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "引擎数据类型.h"
#include "引擎枚举数据.h"

#include <线性代数/矩阵计算.h>
#include <字符串数值互换.h>
#include "动画/an_曲线.h"

#include <zlib.h>





struct S_列表填充数据 {
	std::string					m_ico;
	S_RGBA8UI					m_ico_color;
	std::vector<std::wstring>	m_item;
	std::vector<int32>			m_itemID;
	void* m_Data;
	int32						m_ID_X;
	int32						m_ID_Y;
};

typedef bool(*fp_列表项选中回调)(C_Widget* self, const S_列表填充数据& item);



struct S_PropVecBool{
	std::string		m_ICO;
	std::wstring	m_Names;
	bool			m_Value;
};

struct S_PropVecU8{
	std::string		m_ICO;
	std::wstring	m_Names;
	uint8			m_Value;
};



Inline bool& f_prop_Bool(S_Props& prop) {
	return *((bool*)prop.m_Value);
}

Inline const bool& f_prop_Bool(const S_Props& prop) {
	return *((bool*)prop.m_Value);
}



Inline S_Props f_alloc_UI32FlagBitsProp(uint32* data, std::wstring name) {
	uint8 映射类型;
	if(!data) {
		data = (uint32*)malloc(sizeof(uint32));
		(*data) = 0;
		映射类型 = 0;
	}
	else {
		映射类型 = 1;
	}
	S_Props prop = { E_值类型::e_Type_UI32_FlagBits, (S_结构对象指针)data, name, {}, nullptr, {nullptr}, 32, false, 映射类型 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}


Inline S_Props f_alloc_bool_1DProp(uint8 num, std::wstring name, uint8 min = 0, uint8 max = 255) {
	S_PropVecBool* e = new S_PropVecBool[num];
	for (uint32 i = 0; i < num; ++i) {
		e[i].m_Value = false;
	}

	S_Props prop = { E_值类型::e_Type_Bool_1D, (S_结构对象指针)e, name, {}, nullptr, {nullptr}, num, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_Props f_alloc_u8_1DProp(uint8 num, std::wstring name, uint8 min = 0, uint8 max = 255) {
	S_PropVecU8* e = new S_PropVecU8[num];

	for (uint32 i = 0; i < num; ++i) {
		e[i].m_Value = i;
	}

	S_Props prop = { E_值类型::e_Type_UI8_Array1D, (S_结构对象指针)e, name, {}, nullptr, {nullptr}, num, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}



Inline S_Props f_alloc_iVec3Prop(ivec3* value, std::wstring name, int32 min = 0xffffffff, int32 max = 0x0fffffff) {
	if (value == nullptr) value = (ivec3*)malloc(sizeof(ivec3));
	S_Props prop = { E_值类型::e_Type_iVec3, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 3, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}
Inline ivec3& f_prop_iVec3(S_Props& prop) {
	return *((ivec3*)prop.m_Value);
}



Inline S_Props f_alloc_uVec3Prop(uvec3* value, std::wstring name, float32 min = -3.4E38, float32 max = +3.4E38) {
	if (value == nullptr) value = (uvec3*)malloc(sizeof(uvec3));
	S_Props prop = { E_值类型::e_Type_uVec3, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 3, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}
Inline uvec3& f_prop_uvec3(S_Props& prop) {
	return *((uvec3*)prop.m_Value);
}



inline S_Props f_alloc_Vec4Prop(vec4* value, std::wstring name, float32 min = -3.4E38, float32 max = +3.4E38) {
	if (value == nullptr) value = (vec4*)malloc(sizeof(vec4));
	S_Props prop = { E_值类型::e_Type_Vec4, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 4, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}
Inline vec4& f_prop_Vec4(S_Props& prop) {
	return *((vec4*)prop.m_Value);
}
Inline const vec4& f_prop_Vec4(const S_Props& prop) {
	return *((vec4*)prop.m_Value);
}



Inline S_Props f_alloc_iVec4Prop(ivec4* value, std::wstring name, uint32 min = 0, uint32 max = 0xffffffff) {
	if (value == nullptr) value = (ivec4*)malloc(sizeof(ivec4));
	S_Props prop = { E_值类型::e_Type_iVec4, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 2, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}
Inline ivec4& f_prop_iVec4(S_Props& prop) {
	return *((ivec4*)prop.m_Value);
}



Inline S_Props f_alloc_uVec4Prop(uvec4* value, std::wstring name, int32 min = 0xffffffff, int32 max = 0x0fffffff) {
	if (value == nullptr) value = (uvec4*)malloc(sizeof(uvec4));
	S_Props prop = { E_值类型::e_Type_uVec4, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 2, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}
Inline uvec4& f_prop_uVec4(S_Props& prop) {
	return *((uvec4*)prop.m_Value);
}



Inline int8& f_prop_I8(S_Props& prop) {
	return *((int8*)prop.m_Value);
}
Inline const int8& f_prop_I8(const S_Props& prop) {
	return *((int8*)prop.m_Value);
}

Inline uint8& f_prop_UI8(S_Props& prop) {
	return *((uint8*)prop.m_Value);
}

Inline const uint8& f_prop_UI8(const S_Props& prop) {
	return *((uint8*)prop.m_Value);
}

Inline S_PropVecBool* f_prop_Bool_1D(S_Props& prop) {
	return ((S_PropVecBool*)prop.m_Value);
}
Inline S_PropVecU8* f_prop_UI8_1D(S_Props& prop) {
	return ((S_PropVecU8*)prop.m_Value);
}

Inline float32& f_prop_F32(S_Props& prop) {
	return *((float32*)prop.m_Value);
}
Inline const float32& f_prop_F32(const S_Props& prop) {
	return *((float32*)prop.m_Value);
}

Inline int16& f_prop_I16(S_Props& prop) {
	return *((int16*)prop.m_Value);
}

Inline uint16& f_prop_UI16(S_Props& prop) {
	return *((uint16*)prop.m_Value);
}

Inline const uint16& f_prop_UI16(const S_Props& prop) {
	return *((uint16*)prop.m_Value);
}

Inline int32& f_prop_I32(S_Props& prop) {
	return *((int32*)prop.m_Value);
}

Inline const int32& f_prop_I32(const S_Props& prop) {
	return *((int32*)prop.m_Value);
}


Inline uint32& f_prop_UI32(S_Props& prop) {
	return *((uint32*)prop.m_Value);
}

Inline const uint32& f_prop_UI32(const S_Props& prop) {
	return *((uint32*)prop.m_Value);
}

Inline int64& f_prop_I64(S_Props& prop) {
	return *((int64*)prop.m_Value);
}
Inline uint64& f_prop_UI64(S_Props& prop) {
	return *((uint64*)prop.m_Value);
}


inline vec2& f_prop_Vec2(S_Props& prop) {
	return *((vec2*)prop.m_Value);
}
inline const vec2& f_prop_Vec2(const S_Props& prop) {
	return *((vec2*)prop.m_Value);
}




Inline int32& f_prop_enum(S_Props& prop) {
	return *(((S_PropValueEnum*)prop.m_Value)->m_当前选项);
}
Inline const int32& f_prop_enum(const S_Props& prop) {
	return *(((S_PropValueEnum*)prop.m_Value)->m_当前选项);
}
Inline S_PropValueEnum& f_prop_enumItem(S_Props& prop) {
	return *(((S_PropValueEnum*)prop.m_Value));
}

Inline void f_release_EnumProp(S_Props& prop) {
	delete[](((S_PropValueEnum*)prop.m_Value)->m_ICO);
	delete[](((S_PropValueEnum*)prop.m_Value)->m_Names);
}

void f_prop_Release(S_Props& prop);






std::wstring	f_core_get属性到文本(S_Props prop, uint8 分量 = 0);

void			f_core_字符串到属性(S_Props& prop, const std::wstring& text, uint8 分量 = 0);






/*typedef struct {
	void*			m_Ptr;
	std::wstring*	m_Str;
	std::string		m_Ico;
}S_MapPtrItem;*/
typedef enum : int32 {
	e_项名称改变 = -3,
	e_项删除 = -2,
	e_项添加 = -1,
	e_项选择 = 0,
}E_Prop_MapPtr_项事件类型;

struct S_MapPtrItem {
	void* m_Ptr;
	std::wstring	m_Str;
	std::string		m_Ico;
};

typedef void(*fp_MapPtr元素更新)(S_Props& prop, struct S_MapPtr& self, int32 操作类型);

struct S_MapPtr {
	std::vector<S_MapPtrItem>&	m_PtrItem;
	uint64				m_当前项;
	fp_MapPtr元素更新	mf_元素变更;

	S_MapPtr(std::vector<S_MapPtrItem>& item) : m_PtrItem(item) {}
};

Inline S_MapPtr& f_prop_MapPrt(S_Props& prop) {
	return *((S_MapPtr*)prop.m_Value);
}
Inline uint32 f_prop_MatPtr_切换ID(S_Props& prop, void* ptr) {
	auto& e = *((S_MapPtr*)prop.m_Value);
	auto* data = e.m_PtrItem.data();
	uint32 num = e.m_PtrItem.size();
	for (uint32 i = 0; i < num; ++i) {
		if (data[i].m_Ptr == ptr) {
			e.m_当前项 = i;
			break;
		}
	}
	return e.m_当前项;
}

Inline S_Props f_alloc_StrIndexProp(std::vector<S_MapPtrItem>& item, std::wstring name) {
	//S_MaPtr* e = (S_MaPtr*)calloc(num, sizeof(S_MaPtr));
	S_MapPtr* e = new S_MapPtr(item);
	(*e).m_当前项 = 0;
	(*e).mf_元素变更 = nullptr;
	
	S_Props prop = { E_值类型::e_Type_MapPtr_Array1D, (S_结构对象指针)e, name, {}, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline void f_StrIndexProp_release(S_Props& prop) {
	//S_MaPtr* e = (S_MaPtr*)calloc(num, sizeof(S_MaPtr));
	S_MapPtr& e = f_prop_MapPrt(prop);
	e.m_PtrItem.clear();
}




//struct S_映射引用项 {
//	void* m_Ptr;
//	std::wstring	m_Str;
//	std::string		m_Ico;
//};

typedef void(*fp_映射引用2D_元素更新)(S_Props& prop, struct S_MapPtr& self, int32 操作类型);

struct S_映射引用2D {
	std::vector<std::vector<S_MapPtrItem>*>& m_PtrItem;
	uvec2									 m_当前项;
	fp_列表项选中回调					     mf_元素选择;
	fp_列表项选中回调					     mf_元素添加;
	fp_列表项选中回调					     mf_元素修改;

	S_映射引用2D(std::vector<std::vector<S_MapPtrItem>*>& item) : m_PtrItem(item) {}
};

Inline S_Props f_alloc_MatPtr2DProp(std::vector<std::vector<S_MapPtrItem>*>& item, std::wstring name) {
	S_映射引用2D* e = new S_映射引用2D(item);
	(*e).m_当前项 = {0,0};
	(*e).mf_元素选择 = nullptr;
	(*e).mf_元素添加 = nullptr;
	(*e).mf_元素修改 = nullptr;

	S_Props prop = { E_值类型::e_Type_映射引用_2D, (S_结构对象指针)e, name, {}, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_映射引用2D& f_prop_映射引用2D(S_Props& prop) {
	return *((S_映射引用2D*)prop.m_Value);
}
Inline S_MapPtrItem& f_prop_get2D映射引用项(S_Props& prop, const uvec2& id) {
	return (*(*((S_映射引用2D*)prop.m_Value)).m_PtrItem[id.x])[id.y];
}

Inline void f_prop_映射引用2D_release(S_Props& prop) {
	delete &f_prop_映射引用2D(prop);
	
}








struct S_PropContainer {
	std::vector<S_Props>	m_Item;
	uint64					m_当前项;
	fp_MapPtr元素更新		mf_元素变更;
};

Inline S_Props f_alloc_PropContainer(std::wstring name) {
	S_PropContainer* e = new S_PropContainer;
	e->m_当前项 = 0;
	e->mf_元素变更 = nullptr;

	S_Props prop = { E_值类型::e_Type_PropContainer, (S_结构对象指针)e, name, {}, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_Props f_alloc_PropLayout(std::wstring name, E_值类型 布局类型) {
	if (布局类型 < E_值类型::e_Type_LayoutBegin || 布局类型 > E_值类型::e_Type_LayoutEnd) return {};

	S_PropContainer* e = new S_PropContainer;
	e->m_当前项 = 0;
	e->mf_元素变更 = nullptr;

	S_Props prop = { 布局类型, (S_结构对象指针)e, name, {}, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_PropContainer& f_prop_Container(S_Props& prop) {
	return *((S_PropContainer*)prop.m_Value);
}





Inline S_Props f_alloc_PropArrayContainer(S_Array* val, std::wstring name, E_值类型 type) {
	S_Props prop = { type, (S_结构对象指针)val, name, {}, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_Array* f_prop_ArrayContainer(S_Props& prop) {
	return ((S_Array*)prop.m_Value);
}





struct S_PropList {
	std::list<S_Props>	m_Item;
	uint64				m_当前项;
	fp_MapPtr元素更新	mf_元素变更;
};

Inline S_Props f_alloc_PropList(std::wstring name) {
	S_PropList* e = new S_PropList;
	e->m_当前项 = 0;
	e->mf_元素变更 = nullptr;

	S_Props prop = { E_值类型::e_Type_PropList, (S_结构对象指针)e, name, {}, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_PropList& f_prop_PropList(S_Props& prop) {
	return *((S_PropList*)prop.m_Value);
}



/*typedef enum : uint8 {
	e_Layout_列表,
}E_布局类型;

struct S_PropLayout {
	std::vector<E_布局类型>	m_Item;
	uint64					m_当前项;
	fp_MapPtr元素更新		mf_元素变更;
};*/

Inline S_Props f_alloc_OpsProp(fp_PropUpdate func, const std::wstring& name) {
	S_Props prop = { E_值类型::e_Type_Operator, (S_结构对象指针)nullptr, name, {}, nullptr, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	prop.m_UI->m_Update = func;
	return prop;
}


inline S_Props f_propaAlloc_RGB(vec3* value, std::wstring name) {
	if (value == nullptr) value = (vec3*)malloc(sizeof(vec3));
	S_Props prop = { E_值类型::e_Type_RGB, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 3, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}



Inline S_Props f_alloc_曲线通道Prop(S_曲线通道* value, const std::wstring& name) {
	if (value == nullptr) value = f_an_创建曲线通道(3);

	S_Props prop = { E_值类型::e_Type_2D曲线1D, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_曲线通道* f_prop_Curve(S_Props& prop) {
	return (S_曲线通道*)prop.m_Value;
}


Inline S_Props f_alloc_2DCurveProp(S_曲线* value, const std::wstring& name) {
	if (value == nullptr) value = f_an_创建曲线A();

	S_Props prop = { E_值类型::e_Type_2D曲线, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_曲线* f_prop_2DCurve(S_Props& prop) {
	return (S_曲线*)prop.m_Value;
}
Inline const S_曲线* f_prop_2DCurve(const S_Props& prop) {
	return (S_曲线*)prop.m_Value;
}


Inline S_Props f_alloc_动画曲线层Prop(S_动画曲线组* value, const std::wstring& name) {
	if (value == nullptr) value = f_an_创建曲线层();

	S_Props prop = { E_值类型::e_Type_2D曲线1D, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}



Inline S_Props f_alloc_纹理属性(S_TextueProp* value, const std::wstring& name) {
	if (value == nullptr) {
		value = (S_TextueProp*)malloc(sizeof(S_TextueProp));
		(*value) = { {}, {1,1}, 1, 0 };
	}

	S_Props prop = { E_值类型::e_Type_TexProp, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_TextueProp* f_prop_TexProp(S_Props& prop) {
	return (S_TextueProp*)prop.m_Value;
}





Inline S_Props f_alloc_物体属性(S_OBArray* value, const std::wstring& name) {
	if (value == nullptr) {
		value = (S_OBArray*)f_core_array_new(0, sizeof(S_物体*));
	}

	S_Props prop = { E_值类型::e_Type_Object_1D, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_OBArray* f_prop_物体Prop(S_Props& prop) {
	return (S_OBArray*)prop.m_Value;
}





Inline S_Props f_alloc_键位(S_键位映射* value, const std::wstring& name) {
	assert(value);
	S_Props prop = { E_值类型::e_Type_键位映射, (S_结构对象指针)value, name, {}, nullptr, {nullptr}, 0, false, 0 };
	DEF_alloc_Props_UI_Ptr(prop);
	return prop;
}

Inline S_键位映射* f_prop_键位(S_Props& prop) {
	return (S_键位映射*)prop.m_Value;
}






S_Props f_prop_创建物体类型属性数据();





Inline S_Props f_prop_属性引用(const S_Props& prop) {
	S_Props p = prop;
	p.m_值映射类型 = E_属性引用类型::e_引用;
	DEF_alloc_Props_UI_Ptr(p);
	p.m_私有 = false;
	p.m_UI->m_Update = prop.m_UI->m_Update;
	p.m_UI->m_关键帧 = prop.m_UI->m_关键帧;
	p.m_UI->m_Set = prop.m_UI->m_Set;
	return p;
}


Inline const uint8* f_解字符串(std::string& str, const uint8* data) {
	uint32 num = *((uint32*)data);
	data = &data[sizeof(uint32)];

	str.resize(num);
	memcpy(str.data(), data, num);

	return &data[num];
}

Inline void f_包字符串(S_UI8Array* 块, const std::string& str) {
	uint32 num = str.size();

	f_core_array_push_back_block((S_Array*)块, (uint8*)&num, sizeof(uint32));
	f_core_array_push_back_block((S_Array*)块, (uint8*)str.data(), num);
}




Inline const uint8* f_解宽字符串(std::wstring& str, const uint8* data) {
	uint32 num = *((uint32*)data);
	const uint16* strPtr = (uint16*)&data[sizeof(uint32)];

	str.resize(num);
	for (uint32 i = 0; i < num; ++i) {
		str[i] = strPtr[i];
	}
	return (uint8*)&strPtr[num];
}

Inline void f_包宽字符串(S_UI8Array* 块, const std::wstring& str) {
	uint32 num = str.size();

	f_core_array_push_back_block((S_Array*)块, (uint8*)&num, sizeof(uint32));
	f_core_array_push_back_block((S_Array*)块, (uint8*)str.data(), num * sizeof(uint16));
}


template<typename T>
const uint8* f_文件块_取数据块(T& data, const uint8* data_ptr) {
	data = *((T*)data_ptr);
	return &(data_ptr[sizeof(T)]);
}

template<typename T>
const void f_文件块_写数据块(S_UI8Array* 块, const T& data) {
	f_core_array_push_back_block((S_Array*)块, (uint8*)&data, sizeof(T));
}


Inline const uint8* f_文件块_读数据块(uint8* data, const uint8* data_ptr, uint64 num) {
	memcpy(data, data_ptr, num);
	return &(data_ptr[num]);
}

Inline void f_文件块_写数据块(S_UI8Array* 块, const uint8* data_ptr, uint64 num) {
	f_core_array_push_back_block((S_Array*)块, data_ptr, num);
}




template<typename T>
Inline void f_文件块_写序列数据块(S_UI8Array* 块, const std::vector<T>& 要保存的数据, bool 是否压缩) {
	uint32 点数量 = 要保存的数据.size();
	f_文件块_写数据块(块, 点数量);

	if (是否压缩) {
		std::vector<T> 压缩点(要保存的数据.size());
		uLongf 压缩后大小 = 点数量 * sizeof(T);
		compress((uint8*)压缩点.data(), &压缩后大小, (uint8*)要保存的数据.data(), 压缩后大小);

		uint64 应对ZLIB这种纯类型 = 压缩后大小;
		f_文件块_写数据块(块, 应对ZLIB这种纯类型);
		f_core_array_push_back_block((S_Array*)块, (uint8*)压缩点.data(), 压缩后大小);
	}
	else {
		f_core_array_push_back_block((S_Array*)块, (uint8*)要保存的数据.data(), 点数量 * sizeof(T));
	}
	
}


template<typename T>
Inline const uint8* f_文件块_读序列数据块(const uint8* 下一次读取数据指针, std::vector<T>& 要读取的数据, bool 是否压缩) {
	uint32 点数量 = 0;
	下一次读取数据指针 = f_文件块_取数据块(点数量, 下一次读取数据指针);

	要读取的数据.resize(点数量);
	if (是否压缩) {
		uint64 压缩后大小 = 0;
		下一次读取数据指针 = f_文件块_取数据块(压缩后大小, 下一次读取数据指针);

		uLongf 压缩前大小 = 点数量 * sizeof(T);
		uncompress((uint8*)要读取的数据.data(), &压缩前大小, 下一次读取数据指针, 压缩后大小);

		return &(下一次读取数据指针[压缩后大小]);
	}
	
	return f_文件块_读数据块((uint8*)要读取的数据.data(), 下一次读取数据指针, 点数量 * sizeof(T));
}


